<template>
  <div class="goods-sku" v-for="item in goodsInfo.specs" :key="item.id">
    <dl>
      <dt>{{ item.name }}</dt>
      <dd>
        <template v-for="vals in item.values" :key="vals.name">
          <img
            :class="{ selected: vals.selected, disabled: vals.disabled }"
            @click="changeSku(item, vals)"
            v-if="vals.picture"
            :src="vals.picture"
            alt=""
          />
          <span
            :class="{ selected: vals.selected, disabled: vals.disabled }"
            @click="changeSku(item, vals)"
            v-else
            >{{ vals.name }}</span
          >
        </template>
      </dd>
    </dl>
  </div>
</template>
<script>
import powerSet from '@/vender/power'
const spliter = '@'
// 得到一个路径字典对象
function getPathMap(skus) {
  // 1.得到所有sku集合，props.goodsInfo.skus
  // 2.从所有sku中筛选出有效的sku
  // 3.根据有效的sku使用power-set算法得到子集
  // 4.根据子集往字典路径中存储key-value
  const pathMap = {} // 存放路径字典
  skus.forEach(skuItem => {
    if (skuItem.inventory > 0) {
      // 计算当前有库存的sku的子集
      // 例如：[1,2,3]===[[1],[2],[3],[1,2],[1,3],[2,3],[1,2,3]]
      // 可选值数组
      const valueArr = skuItem.specs.map(val => val.valueName)
      // 可选值数组 子集
      const valueArrPowerSet = powerSet(valueArr)
      // 遍历子集往pathMap中插入数据
      valueArrPowerSet.forEach(arr => {
        // 根据arr得到字符串的key，约定key为['a','b']=>'a@b'
        // const spliter = '@'
        const key = arr.join(spliter)
        // 给pathMap设置数据
        if (pathMap[key]) {
          pathMap[key].push(skuItem.skuCode)
        } else {
          pathMap[key] = [skuItem.skuCode]
        }
      })
      // console.log(key)
      // console.log(skus)
      // console.log(valueArr)
      // console.log(valueArrPowerSet)
    }
  })
  return pathMap
}
// 得到当前选中规格集合
function getSelectedItem(specs) {
  const arr = []
  specs.forEach(item => {
    const selectedValue = item.values.find(val => val.selected)
    arr.push(selectedValue ? selectedValue.name : undefined)
  })
  return arr
}
// 控制按钮是否禁用
function updataDisabledStatus(specs, pathMap) {
  // 1.约定好每个按钮状态由disabled来控制
  specs.forEach((item, i) => {
    const selectedValue = getSelectedItem(specs)
    item.values.forEach(vals => {
      // 2.判断当前是否选中，选中不用判断
      if (vals.selected) return
      // 3.拿当前的值按顺序套入选中值的数组
      selectedValue[i] = vals.name
      // 4.剔除undefind数据，按照分隔符拼接数据
      const key = selectedValue.filter(value => value).join(spliter)
      // 5.去路径字典中查找是否有数据，有就可以点击false，没有就禁用true
      // 找不到返回false，取反true，按钮就会禁用
      vals.disabled = !pathMap[key]
      // console.log(vals)
      // console.log(pathMap[key])
    })
  })
}
// 默认初始化选中按钮
function initDefaultSelected(goodsInfo, skuId) {
  // 1.找到sku信息
  const sku = goodsInfo.skus.find(sku => sku.id === skuId)
  console.log(sku)
  // 2.遍历每一个按钮，按钮的值与sku的值相同就选中
  goodsInfo.specs.forEach((item, i) => {
    const val = item.values.find(vals => vals.name === sku.specs[i].valueName)
    val.selected = true
  })
  // const sku = goods.skus.find(sku => sku.id === skuId)
  // if (sku) {
  //   goods.specs.forEach((spec, i) => {
  //     const value = sku.specs[i].valueName
  //     spec.values.forEach(val => {
  //       val.selected = val.name === value
  //     })
  //   })
  // }
}

export default {
  name: 'GoodsSku',
  props: {
    goodsInfo: {
      type: Object,
      default: () => ({})
    },
    skuId: {
      type: String,
      default: ''
    }
  },
  // 解决子组件向父组件传递自定义事件警告
  emits: ['change'],
  setup(props, { emit }) {
    const pathMap = getPathMap(props.goodsInfo.skus)
    console.log(pathMap)
    // 初始化默认选中
    if (props.skuId) {
      initDefaultSelected(props.goodsInfo, props.skuId)
    }
    // 组件初始化的时候禁用按钮状态
    updataDisabledStatus(props.goodsInfo.specs, pathMap)
    // 1.选中与取消选中，约定在每一个按钮都拥有自己的选中状态数据selected
    // 1.1 点击的是已选中，只需要取消当前的选中
    // 1.2 点击的是未选中，把同一个规格的按钮改成未选中，当前按钮改成选中
    const changeSku = (item, vals) => {
      // 当按钮被禁用是return出去，阻止运行
      if (vals.disabled) return
      if (vals.selected) {
        vals.selected = false
      } else {
        item.values.forEach(valItem => {
          valItem.selected = vals.name === valItem.name ? true : false
        })
        updataDisabledStatus(props.goodsInfo.specs, pathMap)

        // 将你选择的sku信息通知父组件{skuId,price,oldPrice,inventory,specsText}
        // 1.选择完整的sku组合按钮，才可以将信息传递给父组件
        // 2.不是完整的sku组合按钮，传递空对象给父组件

        // 获取到过滤完undefined的数组
        const visibleSelectedSku = getSelectedItem(props.goodsInfo.specs).filter(v => v)
        if (visibleSelectedSku.length === props.goodsInfo.specs.length) {
          console.log('完整')
          const skuIds = pathMap[visibleSelectedSku.join(spliter)]
          const sku = props.goodsInfo.skus.find(val => val.skuCode === skuIds[0])
          // console.log(sku)
          // console.log(skuIds)
          emit('change', {
            skuId: sku.id,
            price: sku.price,
            // 旧价格
            oldPrice: sku.oldPrice,
            // 库存
            inventory: sku.inventory,
            // 属性文字
            specsText: sku.specs
              .reduce((p, c) => {
                return `${p} ${c.name}:${c.valueName}`
              }, '')
              .trim()
          })
        } else {
          console.log('不完整')
          // 不完整传递空对象
          // 父组件需要判断传递的数据是否完整，不完整不能加购物车
          emit('change', {})
        }
        // console.log(visibleSelectedSku)
      }
    }
    return {
      changeSku
    }
  }
}
</script>
<style scoped lang="less">
.sku-state-mixin () {
  border: 1px solid #e4e4e4;
  margin-right: 10px;
  cursor: pointer;

  &.selected {
    border-color: @xtxColor;
  }

  &.disabled {
    opacity: 0.6;
    border-style: dashed;
    cursor: not-allowed;
  }
}

.goods-sku {
  padding-left: 10px;
  padding-top: 20px;

  dl {
    display: flex;
    padding-bottom: 20px;
    align-items: center;

    dt {
      width: 50px;
      color: #999;
    }

    dd {
      flex: 1;
      color: #666;

      > img {
        width: 50px;
        height: 50px;
        .sku-state-mixin ();
      }

      > span {
        display: inline-block;
        height: 30px;
        line-height: 28px;
        padding: 0 20px;
        .sku-state-mixin ();
      }
    }
  }
}
</style>
